# This file is part of Neuroinfo Toolkit.
#
# Neuroinfo Toolkit is free software: you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
# the Free Software Foundation, either version 3 of the License, or
# (at your option) any later version.
#
# Neuroinfo Toolkit is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with Neuroinfo Toolkit.  If not, see <http://www.gnu.org/licenses/>.

import socket
from neuro.exceptions import BaseException
from neuro.exceptions import IllegalArgumentException

class Socket:
	'''
	Socket model
	'''

	def __init__(self, host, port):
		'''
		Constructor

			>>> transport = Transport()
			>>> transport = Transport("www.google.com", 80)
		'''
		self._port = None
		self._host = None
		self._timeout = 10

		self.setHost(host)
		self.setPort(port)

	def setPort(self, port):
		'''
		Set port

			>>> transport.setPort(80)

		:param port:
		:type port: int
		'''
		## --- input validation
		if(not isinstance(port, int)):
			raise IllegalArgumentException("Port must be an instance of int")
		elif(port < 0 or port > 65535):
			raise IllegalArgumentException("Port must be in the range of 0 => 65535")

		self._port = port

	def setHost(self, host):
		'''
		Set hostname

			>>> transport.setHostname("www.google.com")

		:param host:
		:type host: str
		'''
		## --- input validation
		if(not isinstance(host, basestring)):
			raise IllegalArgumentException("Host must be an instance of str")

		host = host.strip()

		if(host == ""):
			raise IllegalArgumentException("Host cannot be empty")

		self._host = host

	def setTimeout(self, timeout=10):
		'''
		Set timeout in seconds

			>>> transport.setTimeout(1000)

		:param timeout: Timeout in seconds
		:type timeout: int
		'''
		## --- input validation
		if(not isinstance(timeout, int)):
			raise IllegalArgumentException("Timeout must be an instance of int")

		if(timeout <= 0):
			raise IllegalArgumentException("Timeout must be greater than 0")

		self._timeout = timeout

	def test(self):
		'''
		Test socket connection

		>>> transport.test()

		:rtype: bool
		'''
		if(self._host == None):
			raise IllegalArgumentException("Host cannot be null")

		if(self._port == None):
			raise IllegalArgumentException("Port cannot be null")

		s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
		s.settimeout(self._timeout)

		try:
			s.connect((self._host, self._port))
		except:
			return False

		s.shutdown(socket.SHUT_RDWR)
		s.close()
		
		return True

class TransportException(BaseException):
	'''
	TCP/IP transport layer exception
	'''
	def __init__(self, desc=""):
		'''
		Constructor

		:param desc:
		:type desc: str
		'''
		BaseException.__init__(self)

		if(desc == None):
			desc = ""

		self._desc = desc;

	def getDescription(self):
		'''
		Get description of this exception

		:rtype: str
		'''
		return self._desc

	def getMessage(self):
		'''
		Get custom message

		:rtype: str
		'''
		return "Transport error: " + self._desc